package com.temp.controller.file;

import com.temp.config.MinioConfig;
import com.temp.controller.utils.MinioUtil;
import com.temp.result.Result;
import io.minio.messages.Bucket;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/file")
@Validated
@Api(tags = "文件存储管理接口")
@Slf4j
public class FileController {

    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private MinioConfig minioConfig;

    @GetMapping("/bucket/exists")
    @ApiOperation("判断存储桶是否存在")
    @RequiresPermissions("file:file:bucketExists")
    public Result<Boolean> bucketExists(
            @ApiParam(value = "存储桶名称", required = true)
            @NotBlank(message = "存储桶名称不能为空")
            @RequestParam("bucketName") String bucketName) {
        try {
            return Result.success(minioUtil.bucketExists(bucketName),"操作成功");
        } catch (Exception e) {
            log.error("检查存储桶是否存在失败: {}", e.getMessage(), e);
            return Result.error("检查存储桶失败: " + e.getMessage());
        }
    }

    @PostMapping("/bucket/create")
    @ApiOperation("创建存储桶")
    @RequiresPermissions("file:file:bucketCreate")
    public Result<Boolean> makeBucket(
            @ApiParam(value = "存储桶名称", required = true)
            @NotBlank(message = "存储桶名称不能为空")
            @RequestParam String bucketName) {
        try {
            return Result.success(minioUtil.makeBucket(bucketName), "存储桶创建成功");
        } catch (Exception e) {
            log.error("创建存储桶失败: {}", e.getMessage(), e);
            return Result.error("创建存储桶失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/bucket/remove")
    @ApiOperation("删除存储桶")
    @RequiresPermissions("file:file:bucketRemove")
    public Result<Boolean> removeBucket(
            @ApiParam(value = "存储桶名称", required = true)
            @NotBlank(message = "存储桶名称不能为空")
            @RequestParam String bucketName) {
        try {
            return Result.success(minioUtil.removeBucket(bucketName), "存储桶删除成功");
        } catch (Exception e) {
            log.error("删除存储桶失败: {}", e.getMessage(), e);
            return Result.error("删除存储桶失败: " + e.getMessage());
        }
    }

    @GetMapping("/bucket/list")
    @ApiOperation("获取所有存储桶列表")
    @RequiresPermissions("file:file:bucketList")
    public Result<List<Bucket>> getAllBuckets() {
        try {
            return Result.success(minioUtil.getAllBuckets(),"操作成功");
        } catch (Exception e) {
            log.error("获取存储桶列表失败: {}", e.getMessage(), e);
            return Result.error("获取存储桶列表失败: " + e.getMessage());
        }
    }

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation("文件上传")
    @RequiresPermissions("file:file:upload")
    public Result<String> upload(
            @ApiParam(value = "上传的文件", required = true)
            @RequestPart("file") MultipartFile file,

            @ApiParam(value = "存储桶名称，不传则使用默认存储桶")
            @RequestParam(value = "bucketName", required = false) String bucketName,

            @ApiParam(value = "自定义文件路径（如 'user/avatar/'）")
            @RequestParam(value = "path", required = false) String path) {
        try {
            if (file.isEmpty()) {
                return Result.error("上传文件不能为空");
            }

            // 检查文件大小限制
            if (file.getSize() > minioConfig.getMaxFileSize()) {
                return Result.error("文件大小超过限制");
            }

            // 使用指定存储桶或默认存储桶
            String targetBucket = StringUtils.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();

            String objectName = minioUtil.upload(file, targetBucket, path);
            if (StringUtils.isNotBlank(objectName)) {
                String url = minioUtil.getFileUrl(targetBucket, objectName);
                return Result.success(url, "文件上传成功");
            }
            return Result.error("文件上传失败");
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage(), e);
            return Result.error("文件上传失败: " + e.getMessage());
        }
    }

    @PostMapping("/upload/batch")
    @ApiOperation("批量文件上传")
    @RequiresPermissions("file:file:uploadBatch")
    public Result<Map<String, String>> uploadBatch(
            @ApiParam(value = "上传的文件列表", required = true)
            @RequestPart("files") MultipartFile[] files,

            @ApiParam(value = "存储桶名称，不传则使用默认存储桶")
            @RequestParam(value = "bucketName", required = false) String bucketName,

            @ApiParam(value = "自定义文件路径（如 'user/avatar/'）")
            @RequestParam(value = "path", required = false) String path) {
        try {
            if (files == null || files.length == 0) {
                return Result.error("上传文件列表不能为空");
            }

            // 使用指定存储桶或默认存储桶
            String targetBucket = StringUtils.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();

            Map<String, String> result = minioUtil.uploadBatch(files, targetBucket, path);
            return Result.success(result, "批量上传完成");
        } catch (Exception e) {
            log.error("批量文件上传失败: {}", e.getMessage(), e);
            return Result.error("批量文件上传失败: " + e.getMessage());
        }
    }

    @GetMapping("/preview")
    @ApiOperation("文件预览")
    @RequiresPermissions("file:file:preview")
    public Result<String> preview(
            @ApiParam(value = "文件名", required = true)
            @NotBlank(message = "文件名不能为空")
            @RequestParam String fileName,

            @ApiParam(value = "存储桶名称，不传则使用默认存储桶")
            @RequestParam(value = "bucketName", required = false) String bucketName) {
        try {
            String targetBucket = StringUtils.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();
            return Result.success(minioUtil.preview(targetBucket, fileName));
        } catch (Exception e) {
            log.error("文件预览失败: {}", e.getMessage(), e);
            return Result.error("文件预览失败: " + e.getMessage());
        }
    }

    @GetMapping("/download")
    @ApiOperation("文件下载")
    @RequiresPermissions("file:file:download")
    public void download(
            @ApiParam(value = "文件名", required = true)
            @NotBlank(message = "文件名不能为空")
            @RequestParam String fileName,

            @ApiParam(value = "存储桶名称，不传则使用默认存储桶")
            @RequestParam(value = "bucketName", required = false) String bucketName,

            @ApiParam(value = "是否作为附件下载", defaultValue = "true")
            @RequestParam(defaultValue = "true") boolean attachment,

            HttpServletResponse response) {
        try {
            String targetBucket = StringUtils.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();
            minioUtil.download(targetBucket, fileName, attachment, response);
        } catch (Exception e) {
            log.error("文件下载失败: {}", e.getMessage(), e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    @DeleteMapping("/delete")
    @ApiOperation("删除文件")
    @RequiresPermissions("file:file:delete")
    public Result<Boolean> remove(
            @ApiParam(value = "文件URL或对象名称", required = true)
            @NotBlank(message = "文件标识不能为空")
            @RequestParam String fileIdentifier,

            @ApiParam(value = "存储桶名称，不传则使用默认存储桶")
            @RequestParam(value = "bucketName", required = false) String bucketName) {
        try {
            String targetBucket = StringUtils.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();

            // 如果传入的是URL，则解析出对象名称
            String objectName;
            if (fileIdentifier.startsWith("http")) {
                objectName = fileIdentifier.substring(fileIdentifier.lastIndexOf(targetBucket + "/") + targetBucket.length() + 1);
            } else {
                objectName = fileIdentifier;
            }

            minioUtil.remove(targetBucket, objectName);
            return Result.success(true, "文件删除成功");
        } catch (Exception e) {
            log.error("文件删除失败: {}", e.getMessage(), e);
            return Result.error("文件删除失败: " + e.getMessage());
        }
    }

    @GetMapping("/info")
    @ApiOperation("获取文件信息")
    @RequiresPermissions("file:file:info")
    public Result<Map<String, Object>> getFileInfo(
            @ApiParam(value = "文件名", required = true)
            @NotBlank(message = "文件名不能为空")
            @RequestParam String fileName,

            @ApiParam(value = "存储桶名称，不传则使用默认存储桶")
            @RequestParam(value = "bucketName", required = false) String bucketName) {
        try {
            String targetBucket = StringUtils.isNotBlank(bucketName) ? bucketName : minioConfig.getBucketName();
            return Result.success(minioUtil.getFileInfo(targetBucket, fileName),"操作成功");
        } catch (Exception e) {
            log.error("获取文件信息失败: {}", e.getMessage(), e);
            return Result.error("获取文件信息失败: " + e.getMessage());
        }
    }
}